using System;
using Aop.Api.Domain;
using S7.Net;
using WCS.Application.Service.Plc;
using DataType = S7.Net.DataType;

public class ConveyorSystemCommand
{
    // 字段偏移量定义（基于每台设备30字节，数据结构占28字节，后2位预留）
    public static class Offsets
    {
        public const int ReadFlag = 0;           // 1字节
        public const int AckFlag = 1;            // 1字节
        public const int Command = 2;            // 1字节
        public const int TaskType = 3;           // 1字节
        public const int DeviceNo = 4;           // 4字节
        public const int TaskNo = 8;             // 4字节
        public const int ContainerNo = 12;       // 8字节
        public const int StartPosition = 20;     // 4字节
        public const int TargetPosition = 24;    // 4字节
        public const int Rel0 = 28;              // 2字节（预留）
    }

    // 设备基地址和偏移量设置
    private readonly int _baseDbNumber;
    private readonly int _deviceIndex;
    
    // 数据字段
    public short ReadFlag { get; set; }
    public short AckFlag { get; set; }
    public short Command { get; set; }
    public short TaskType { get; set; }
    public int DeviceNo { get; set; }
    public int TaskNo { get; set; }
    public string ContainerNo { get; set; }
    public int StartPosition { get; set; }
    public int TargetPosition { get; set; }
    public int Rel0 { get; set; }
    
    // 指令常量定义
    public static class Commands
    {
        public const short Move = 1;
        public const short Remove = 2;
        public const short OutboundRequest = 4;
        public const short HoistMove = 11;
        public const short HoistUnlock = 12;
    }
    
    // 任务类型常量定义
    public static class TaskTypes
    {
        public const short PointMove = 1;
        public const short PalletCodeWrite = 2;
    }
    
    // 构造函数
    public ConveyorSystemCommand(int baseDbNumber, int deviceIndex)
    {
        _baseDbNumber = baseDbNumber;
        _deviceIndex = deviceIndex;
    }
    
    // 计算当前设备的实际DB地址
    private int CalculateDbAddress(int offset)
    {
        return offset + (_deviceIndex * 30); // 每台设备偏移30字节
    }

    // 从PLC读取数据
    public void ReadFromPlc(Plc plc)
    {
        if (!plc.IsConnected)
            throw new InvalidOperationException("PLC未连接");

        try
        {
            // 修复CS7036错误：添加缺少的参数“varCount”  
            ReadFlag = Convert.ToInt16(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.ReadFlag), VarType.Byte, 1));
            AckFlag = Convert.ToInt16(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.AckFlag), VarType.Byte, 1));
            Command = Convert.ToInt16(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.Command), VarType.Byte, 1));
            TaskType = Convert.ToInt16(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TaskType), VarType.Byte, 1));
            DeviceNo = Convert.ToInt32(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.DeviceNo), VarType.DWord, 1));
            TaskNo = Convert.ToInt32(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TaskNo), VarType.DWord, 1));

            // 读取ContainerNo (8字节字符串)  
            byte[] containerBytes = (byte[])plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.ContainerNo), VarType.Byte, 8);
            ContainerNo = System.Text.Encoding.ASCII.GetString(containerBytes);

            StartPosition = Convert.ToInt32(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.StartPosition), VarType.DWord, 1));
            TargetPosition = Convert.ToInt32(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TargetPosition), VarType.DWord, 1));
            Rel0 = Convert.ToInt32(plc.Read(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.Rel0), VarType.Word, 1));
        }
        catch (Exception ex)
        {
            Console.WriteLine($"读取PLC数据时出错: {ex.Message}");
            throw;
        }
    }


    // 写入数据到PLC
    public void WriteToPlc(Plc plc)
    {
        if (!plc.IsConnected)
            throw new InvalidOperationException("PLC未连接");
            
        try
        {
            // 写入各个字段

            // Fix for CS1061: Replace "DBWrite" with "Write" as "Plc" does not have a "DBWrite" method.
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.ReadFlag), (byte)ReadFlag);

            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.AckFlag), (byte)AckFlag);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.Command), (byte)Command);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TaskType), (byte)TaskType);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.DeviceNo), DeviceNo);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TaskNo), TaskNo);

            // Writing ContainerNo (8-byte string)
            byte[] containerBytes = System.Text.Encoding.ASCII.GetBytes(ContainerNo.PadRight(8, ' '));
            plc.WriteBytes(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.ContainerNo), containerBytes);

            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.StartPosition), StartPosition);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.TargetPosition), TargetPosition);
            plc.Write(DataType.DataBlock, _baseDbNumber, CalculateDbAddress(Offsets.Rel0), (short)Rel0);

           
        }
        catch (Exception ex)
        {
            Console.WriteLine($"写入PLC数据时出错: {ex.Message}");
            throw;
        }
    }
    
    // 数据验证方法
    public bool IsValid()
    {
        // 验证ReadFlag
        if (ReadFlag != 1 && ReadFlag != 2)
            return false;
            
        // 验证AckFlag
        if (AckFlag != 1 && AckFlag != 2)
            return false;
            
        // 验证Command
        if (!IsValidCommand(Command))
            return false;
            
        // 验证TaskType与Command的关联
        if (Command == Commands.Move && TaskType != TaskTypes.PointMove)
            return false;
            
        // 验证DeviceNo格式(3位数字)
        if (DeviceNo < 100 || DeviceNo > 999)
            return false;
            
        // 验证TaskNo范围
        if (TaskNo < 10000 || TaskNo > 99999)
            return false;
            
        // 验证ContainerNo格式
        if (!IsValidContainerNo(ContainerNo))
            return false;
            
        // 验证位置编码格式
        if (StartPosition < 100 || StartPosition > 999 || 
            TargetPosition < 100 || TargetPosition > 999)
            return false;
            
        return true;
    }
    
    private bool IsValidCommand(short command)
    {
        // 检查是否为有效指令
        return command switch
        {
            Commands.Move => true,
            Commands.Remove => true,
            Commands.OutboundRequest => true,
            Commands.HoistMove => true,
            Commands.HoistUnlock => true,
            _ => command >= 1 && command <= 99,
        };
    }
    
    private bool IsValidContainerNo(string containerNo)
    {
        if (string.IsNullOrEmpty(containerNo) || containerNo.Length != 8)
            return false;
            
        // 前两位为字母
        if (!char.IsLetter(containerNo[0]) || !char.IsLetter(containerNo[1]))
            return false;
            
        // 后五位为数字
        for (int i = 2; i < 8; i++)
        {
            if (!char.IsDigit(containerNo[i]))
                return false;
        }
        
        return true;
    }
}    